package com.snake.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snake.models.WxComponentToken;
import com.snake.util.aes.AesException;
import com.snake.util.aes.WXBizMsgCrypt;

/*
 * 微信第三方开发工具
 */
public class ComponentWxUtil implements Serializable{
	public static Logger logger = Logger.getLogger(ComponentWxUtil.class.getName());  
	/**
     * 微信全网测试账号
     */
   /* private final static String COMPONENT_TOKEN = "ghBgmhtca1Wz1WMPBD4dt1GHMpgmh1HM";
    private final static String COMPONENT_ENCODINGAESKEY = "tj2UJu8ZuhGup6dYBYdD98d6dTcHoD26T52WO82DDdH";
    private final static String APPID="wxa6e3656a6d7d73a5";*/
    /**
     * 授权事件接收
     * 
     * @param request
     * @param response
     * @throws IOException
     * @throws AesException
     * @throws DocumentException
     */
    public void acceptAuthorizeEvent(HttpServletRequest request,
            HttpServletResponse response) throws IOException, AesException,
            DocumentException {
         System.out.println("微信第三方平台---------微信推送Ticket消息10分钟一次-----------");
        // DataUtils.getDataString(DataUtils.yyyymmddhhmmss));
        
       // String processAuthorizeEvent = processAuthorizeEvent(request);
        //
        //output(response, processAuthorizeEvent); // 输出响应的内容。
    }
    /**
     * 处理授权事件的推送
     * 
     * @param request
     * @throws IOException
     * @throws AesException
     * @throws DocumentException
     */
    public static String processAuthorizeEvent(HttpServletRequest request,String componentToken,String componentEncodingaeskey,String componentAppid,String appid)
            throws IOException, DocumentException, AesException {
        String nonce = request.getParameter("nonce");
        String timestamp = request.getParameter("timestamp");
        String msgSignature = request.getParameter("msg_signature");
        System.out.print(nonce+"  "+timestamp+"  "+msgSignature);
        logger.error("微信开发:"+nonce+"  "+timestamp+"  "+msgSignature);
        new WXBizMsgCrypt(componentToken,componentEncodingaeskey,componentAppid);
        StringBuilder sb = new StringBuilder();
        BufferedReader in = request.getReader();
        String line;
        while ((line = in.readLine()) != null) {
            sb.append(line);
        }
        String xml = sb.toString();
        System.out.println("第三方平台全网发布-----------------------原始 Xml="+xml);
        logger.error("微信开发第三方平台全网发布-----------------------原始 Xml="+xml);
        String encodingAesKey = componentEncodingaeskey;// 第三方平台组件加密密钥
        // LogUtil.info("第三方平台全网发布-------------appid----------getAuthorizerAppidFromXml(xml)-----------appId="+appId);
        System.out.println("第三方平台全网发布-----------------------getThirdWeixinBase.toString():");
       
        WXBizMsgCrypt pc = new WXBizMsgCrypt(componentToken, encodingAesKey,
        		appid);
        System.out.println("第三方平台全网发布-----------------------解密 WXBizMsgCrypt new 成功");
        logger.error("第三方平台全网发布-----------------------解密 WXBizMsgCrypt new 成功");
        String xml1 = pc.decryptMsg(msgSignature, timestamp, nonce, xml);
        System.out.println("第三方平台全网发布-----------------------解密后 Xml="+xml1);
        logger.error("第三方平台全网发布-----------------------解密后 Xml="+xml1);
        String processAuthorizationEvent = processAuthorizationEvent(xml1);
        return processAuthorizationEvent;
    }

      /**
       * 解密Ticket
       * 
       * @param xml
       */
      static String processAuthorizationEvent(String xml) {
          Document doc;
          try {
              doc = DocumentHelper.parseText(xml);
              Element rootElt = doc.getRootElement();
              String ticket = rootElt.elementText("ComponentVerifyTicket");
              System.out.println("第三方平台全网发布-----------------------解密后 ComponentVerifyTicket="+ticket);
              logger.error("第三方平台全网发布-----------------------解密后 ComponentVerifyTicket="+ticket);
              if(ticket != null && !ticket.equals("")){
            	  return ticket;
              }
          } catch (DocumentException e) {
              e.printStackTrace();
          }
  		return "";
      }
      /**
       * 获取授权的Appid
       * 
       * @param xml
       * @return
       */
      String getAuthorizerAppidFromXml(String xml) {
          Document doc;
          try {
              doc = DocumentHelper.parseText(xml);
              Element rootElt = doc.getRootElement();
              String toUserName = rootElt.elementText("ToUserName");
              return toUserName;
          } catch (DocumentException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
          return null;
      }
      /**
       * 
       * @param response
       * @param returnvaleue
       */
      public static void output(HttpServletResponse response, String returnvaleue) {
          try {
              PrintWriter pw = response.getWriter();
              pw.write(returnvaleue);
              // System.out.println("****************returnvaleue***************="+returnvaleue);
              pw.flush();
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
    //检验accessToken有效期
  	public static boolean tokenIsValidity(WxComponentToken wxComponentToken) throws ParseException {
  		//Token token
  		String accessToken = "";
  		Long accessExpires =0L;
  		boolean bo = true;
  		if(wxComponentToken!=null&&!wxComponentToken.getComponentValue().equals("")){
  			accessToken=wxComponentToken.getComponentValue();
  			long timess = DateUtil.getTimess(wxComponentToken.getExpiresIn());
  			accessExpires=timess;
  			if(accessToken.equals("")||accessExpires==0){
  				//jsonObject = getWXAccessToken(appid, appsecret);
  				bo = false;
  			}else{
  				long currentTimeMillis = System.currentTimeMillis();
  				if (currentTimeMillis >=accessExpires) {
  					bo = false;
  				}else{
  					bo = true;
  					return bo;
  				}
  			}
  		}else{
  			bo = false;
  		}
  		return bo;
  	}
      /**
  	 * 获取access_token
  	 * 
  	 * @param appid
  	 *            凭证
  	 * @param appsecret
  	 *            密钥
  	 * @return
     * @throws JsonProcessingException 
  	 */
  	public static Map<String, Object> getComponentAccessToken(String componentAppid, String componentAppsecret,String componentVerifyTicket) throws JsonProcessingException {
  		String requestUrl = "https://api.weixin.qq.com/cgi-bin/component/api_component_token";
  		Map<String, Object> mp = new HashMap<String, Object>();
  		mp.put("component_appid", componentAppid);
  		mp.put("component_appsecret", componentAppsecret);
  		mp.put("component_verify_ticket", componentVerifyTicket);
  		ObjectMapper mapper = new ObjectMapper();
		String writeValueAsString = mapper.writeValueAsString(mp);
  		JSONObject jsonObject = HttpClientUtil.httpRequest(requestUrl, "POST", writeValueAsString);
  		Map<String, Object> map = new HashMap<String, Object>();
  		System.out.println("----------------getWXAccessToken:"+jsonObject.toString());
  		// 如果请求成功
  		if (jsonObject != null && jsonObject.containsKey("component_access_token")
  				&& jsonObject.containsKey("expires_in")) {
  			long currentTimeMillis = (System.currentTimeMillis()) / 1000;
  			long expiresIn = jsonObject.getLong("expires_in");
  			Long c = currentTimeMillis + expiresIn;
  			SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
  					"yyyy-MM-dd HH:mm:ss");
  			Date date = new Date(c * 1000);
  			String accessExpires = simpleDateFormat.format(date);
  			
  			map.put("accessExpires", accessExpires);
  			map.put("componentAccessToken", jsonObject.getString("component_access_token"));
  		} else {
  			logger.error("获取ComponentAccessToken失败 errcode:"+
  					jsonObject.getInt("errcode")+",errmsg:"+
  					jsonObject.getString("errmsg"));
  			return map;
  		}
  		return map;
  	}
    /**
  	 * 获取预授权码pre_auth_code
  	 * 
  	 * @param component_access_token
  	 *            凭证
  	 * @param component_appid
  	 *           第三方appid
  	 * @return
     * @throws JsonProcessingException 
  	 */
  	public static Map<String, Object> getPreAuthCode(String componentAppid, String componentAccessToken) throws JsonProcessingException {
  		String requestUrl = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=COMPONENT_ACCESS_TOKEN".replace("COMPONENT_ACCESS_TOKEN", componentAccessToken);
  		Map<String, Object> mp = new HashMap<String, Object>();
  		mp.put("component_appid", componentAppid);
  		ObjectMapper mapper = new ObjectMapper();
		String writeValueAsString = mapper.writeValueAsString(mp);
  		JSONObject jsonObject = HttpClientUtil.httpRequest(requestUrl, "POST", writeValueAsString);
  		Map<String, Object> map = new HashMap<String, Object>();
  		System.out.println("----------------getWXAccessToken:"+jsonObject.toString());
  		// 如果请求成功
  		if (jsonObject != null && jsonObject.containsKey("pre_auth_code")
  				&& jsonObject.containsKey("expires_in")) {
  			long currentTimeMillis = (System.currentTimeMillis()) / 1000;
  			long expiresIn = jsonObject.getLong("expires_in");
  			Long c = currentTimeMillis + expiresIn;
  			SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
  					"yyyy-MM-dd HH:mm:ss");
  			Date date = new Date(c * 1000);
  			String accessExpires = simpleDateFormat.format(date);
  			
  			map.put("accessExpires", accessExpires);
  			map.put("preAuthCode", jsonObject.getString("pre_auth_code"));
  		} else {
  			logger.error("获取pre_auth_code失败 errcode:"+
  					jsonObject.getInt("errcode")+",errmsg:"+
  					jsonObject.getString("errmsg"));
  			return map;
  		}
  		return map;
  	}
  	/**
  	 * 获取预授权码pre_auth_code
  	 * 
  	 * @param component_access_token
  	 *            凭证
  	 * @param component_appid
  	 *           第三方appid
  	 * @return
     * @throws JsonProcessingException 
  	 */
  	public static Map<String, Object> getAuthorizationInfo(String componentAppid, String componentAccessToken,String authorizationCode) throws JsonProcessingException {
  		String requestUrl = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=COMPONENT_ACCESS_TOKEN".replace("COMPONENT_ACCESS_TOKEN", componentAccessToken);
  		Map<String, Object> mp = new HashMap<String, Object>();
  		mp.put("component_appid", componentAppid);
  		mp.put("authorization_code", authorizationCode);
  		ObjectMapper mapper = new ObjectMapper();
		String writeValueAsString = mapper.writeValueAsString(mp);
  		JSONObject jsonObject = HttpClientUtil.httpRequest(requestUrl, "POST", writeValueAsString);
  		Map<String, Object> map = new HashMap<String, Object>();
  		System.out.println("----------------getAuthorizationInfo()--:"+jsonObject.toString());
  		// 如果请求成功
  		if (jsonObject != null && jsonObject.containsKey("authorization_info")) {
  			jsonObject.getString("authorization_info");
  			JSONObject authorizationInfo = jsonObject.getJSONObject("authorization_info");
  			String authorizerAppid = authorizationInfo.getString("authorizer_appid");
  			String authorizerAccessToken = authorizationInfo.getString("authorizer_access_token");
  			String authorizerRefreshToken = authorizationInfo.getString("authorizer_refresh_token");
  			long expiresIn = jsonObject.getLong("expires_in");
  			long currentTimeMillis = (System.currentTimeMillis()) / 1000;
  			Long c = currentTimeMillis + expiresIn;
  			SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
  					"yyyy-MM-dd HH:mm:ss");
  			Date date = new Date(c * 1000);
  			String accessExpires = simpleDateFormat.format(date);
  			map.put("accessExpires", accessExpires);
  			map.put("authorizerAppid", authorizerAppid);
  			map.put("authorizerAccessToken", authorizerAccessToken);
  			map.put("authorizerRefreshToken", authorizerRefreshToken);
  		} else {
  			logger.error("获取AuthorizationInfo失败 errcode:"+
  					jsonObject.getInt("errcode")+",errmsg:"+
  					jsonObject.getString("errmsg"));
  			return map;
  		}
  		return map;
  	} 
  }
